package com.sikadwafastdaisfondturbo.pretloan.utils.event.track

import android.annotation.SuppressLint
import android.content.Context
import com.sikadwafastdaisfondturbo.pretloan.utils.log.HHLog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.coroutines.coroutineContext

/**
 * 埋点管理器
 */
@SuppressLint("StaticFieldLeak")
object TrackEventManager {
    private lateinit var dao: TrackEventDao
    private var trackUploader: TrackEventUploader = SikadwaTrackEventUploader()

    // Coroutine Scope
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())

    /** 上传操作的互斥锁 */
    private val uploadMutex = Mutex()

    /** 释放任务的状态 */
    private var isDestroyed = AtomicBoolean(false)

    /** 当前在上传的任务 */
    private var currentUploadJob: Job? = null

    /** 初始化方法 */
    fun init(context: Context) {
        dao = TrackEventDatabase.getDatabase(context).eventDao()
        HHLog.d("TrackEventManager initialized")
    }

    /** 释放 */
    fun destroy() {
        if (isDestroyed.compareAndSet(false, true)) {
            scope.cancel()
            HHLog.d("TrackEventManager destroyed")
        }
    }

    /** 记录埋点事件 */
    fun trackEvent(type: String, remark: String?) {
        scope.launch(Dispatchers.IO) {
            val event = TrackEvent(type.uppercase(), remark)
            dao.insert(event)
            HHLog.d("TrackEventManager Event recorded: $type,$remark")
        }
    }

    /** 记录埋点事件，并立即上传 */
    fun trackEventNow(type: String, remark: String?) {
        scope.launch(Dispatchers.IO) {
            val event = TrackEvent(type = type.uppercase(), remark = remark)
            dao.insert(event)
            HHLog.d("TrackEventManager Event recorded: $type")

            performUpload()
        }
    }

    /** 主动上传未上传的埋点事件 */
    fun uploadEvents() {
        scope.launch(Dispatchers.IO) {
            try {
                if (!isActive) return@launch
                performUpload()
            } catch (e: Exception) {
                HHLog.d("TrackEventManager Manual upload failed: ${e.message}")
            }
        }
    }

    /** 通用的上传逻辑 */
    private suspend fun performUpload() {
        currentUploadJob?.cancel()
        if (!coroutineContext.isActive) return

        uploadMutex.withLock {
            if (!coroutineContext.isActive) return

            val events = dao.getUnsentEvents()
            if (events.isNotEmpty()) {
                currentUploadJob = scope.launch(Dispatchers.IO) {
                    retryWithBackoff(maxRetries = 3) {
                        val uploadJob = async { trackUploader.upload(events) }
                        val eventIds = events.map { it.id.toLong() }
                        val markJob = async {
                            dao.markAsUploaded(eventIds)
                            dao.deleteUploadedEvents(eventIds)
                        }

                        uploadJob.await()
                        markJob.await()
                        HHLog.d("TrackEventManager ${events.size} events as uploaded")
                    }
                }
            }
        }
    }

    /** 重试上传机制 */
    private suspend fun <T> retryWithBackoff(maxRetries: Int, initialDelayMillis: Long = 1000, block: suspend () -> T): T {
        var currentDelay = initialDelayMillis
        repeat(maxRetries - 1) {
            try {
                return block()
            } catch (e: Exception) {
                HHLog.d("TrackEventManager Retrying after failure: ${e.message}")
            }
            delay(currentDelay)
            currentDelay *= 2
        }
        return block()
    }
}